/*
 * @Author: mengxianwei mxw1@meitu.com
 * @Date: 2024-09-06 11:38:36
 * @LastEditors: mengxianwei mxw1@meitu.com
 * @LastEditTime: 2024-10-10 15:25:10
 *
 * @Description:
 * 美图云修QT 组件规范化 --- 滑动条组件
 *
 * 根据业务需求定制化实现 QSlider 控件，
 *
 * 滑轨支持线性渐变颜色
 *
 * 仅支持正整数范围内的范围值
 *
 */

#ifndef MLADDERSTEPSLIDER_H
#define MLADDERSTEPSLIDER_H

#include <QPropertyAnimation>
#include <QWidget>
#include <tuple>

class MLadderStepSlider : public QWidget
{
    Q_OBJECT
  public:
    enum StateStyle
    {
        STYLE_NORMAL = 0,
        STYLE_HOVER,
        STYLE_DISABLE
    };

    enum TextAlignment
    {
        ALIGN_LEFT = 0x0001,
        ALIGN_RIGHT = 0x0002,
        ALIGN_HCENTER = 0x0004,
        ALIGN_TOP = 0x0020,
        ALIGN_BOTTOM = 0x0040,
        ALIGN_VCENTER = 0x0080,
    };
    /**
     * @description:              创建自定已滑动条对象
     * @param {QWidget} *parent   父窗口指针
     * @return {*}
     */
    explicit MLadderStepSlider(QWidget *parent = nullptr);

    /**
     * @description:    这是滑动条最大值与最小值，需保证最小值小于最大值，内部未做校验
     * @param {int} min 最小值
     * @param {int} max 最大值
     * @return {*}
     */
    void setRange(int min, int max);

    /**
     * @description: 获取滑动条最大值
     * @return {*}
     */
    [[nodiscard]] int minimum() const;

    /**
     * @description: 获取滑动条最小值
     * @return {*}
     */
    [[nodiscard]] int maximum() const;

    /**
     * @description:      设置滑动条当前值
     * @param {int} value 当前值
     * @return {*}
     */
    void setValue(int value);

    /**
     * @description: 返回滑动条当前值
     * @return {*}
     */
    [[nodiscard]] int value() const;

    /**
     * @description:      设置滑动条双击滑块时默认值
     * @param {int} value 默认值
     * @return {*}
     */
    void setDefaultValue(int value);

    /**
     * @description:            开启/关闭 滑块点击动画
     * @param {bool} isEnable   是否开启 true-开启 false- 关闭
     * @param {borderMaxWidth}  borderMaxWidth 滑块边框最大值
     * @return {*}
     *
     * 该接口需要在完成相关样式设置后调用
     */
    void setEnableHandleAnimation(bool isEnable, int borderMaxWidth);

    void setSingleStep(int step);

    void setStepRules(const std::vector<std::tuple<int, int, int, int>> &rulesTuple);

    void setEventEnable(bool isEnable);

    void setHoverState(bool isHover);

    bool isChangeValueIng();

    /**
     * @description:          设置滑动条文字内容
     * @param {QString&} text 文字内容
     * @param {int} flag      文字在滑动条内的对其方式
     * @return {*}
     */
    void setText(const QString &text, int flag);

    /**
     * @description:              设置文字样式
     * @param {QFont&} font       文字 font
     * @param {QColor} &color     文字颜色
     * @param {StateStyle} state  滑动条状态
     * @return {*}
     */
    void setTextStyle(const QFont &font, const QColor &color, StateStyle state);

    /**
     * @description:              设置滑动条背景色
     * @param {QColor} &color     背景色
     * @param {StateStyle} state  滑动条状态
     * @return {*}
     */
    void setBgStyle(const QColor &color, StateStyle state);

    /**
     * @description:                      设置滑动条滑轨样式
     * @param {int} height                滑轨高度
     * @param {int} radius                滑轨圆角
     * @param {QList<QColor>} &colorList  滑轨背景色，支持线性渐变
     * @param {StateStyle} state          滑动条状态
     * @return {*}
     */
    void setGrooveBgStyle(int height, int radius, const QList<QColor> &colorList, StateStyle state);

    /**
     * @description:                      设置滑动条已滑动区域颜色，支持单色和双色模式（见文件注释）
     * @param {QList<QColor>} &colorList  背景色，支持线性渐变
     * @param {StateStyle} state          滑动条状态
     * @return {*}
     */
    void setSubPageBgStyle(const QList<QColor> &colorList, StateStyle state);

    /**
     * @description:                设置滑块样式
     * @param {int} width           滑块宽度
     * @param {int} height          滑块高度
     * @param {int} radius          滑块圆角
     * @param {QColor} &color       滑块背景色
     * @param {StateStyle} state    滑动条状态
     * @return {*}
     */
    void setHandleBgStyle(int width, int height, int radius, const QColor &color, StateStyle state);

    /**
     * @description:              设置滑块边框样式
     * @param {int} width         边框宽度
     * @param {QColor} &color     边框颜色
     * @param {StateStyle} state  滑动条状态
     * @return {*}
     */
    void setHandleBorderStyle(int width, const QColor &color, StateStyle state);

  signals:
    /**
     * @description:        通知当前正在拖动滑块的值
     * @param {int} value   滑动条当前值
     * @return {*}
     */
    void valueChanging(int value);

    /**
     * @description:        滑动条的最终值
     * @param {int} value   滑动条当前值
     * @return {*}
     */
    void valueChanged(int value);

    /**
     * @description:        通知当前按下滑块
     * @param {int} value   滑动条当前值
     * @return {*}
     */
    void sliderHandlePress(int value);

    /**
     * @description:        通知当前正在松开滑块
     * @param {int} value   滑动条当前值
     * @return {*}
     */
    void sliderHandleRelease(int value);

  protected:
    void paintEvent(QPaintEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;
    void showEvent(QShowEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseDoubleClickEvent(QMouseEvent *event) override;
    void enterEvent(QEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void keyPressEvent(QKeyEvent *ev) override;
    void keyReleaseEvent(QKeyEvent *event) override;
    void wheelEvent(QWheelEvent *e) override;

  private:
    // 绘制滑动条背景
    void drawSliderBg(QPainter *painter);
    // 绘制滑动条滑轨
    void drawSliderGroove(QPainter *painter);
    // 绘制已划过区域颜色
    void drawSliderSubPage(QPainter *painter);
    // 绘制滑块
    void drawSliderHandle(QPainter *painter);
    // 绘制文字
    void drawSliderText(QPainter *painter);

  private:
    // 重新计算矩形大小
    inline void recalculateRectangle();
    // 计算滑块位置
    inline QPointF calculateSliderHandlePos();
    // 计算当前值
    inline int calculateCurValue(int mousePosX);
    // 设置默认样式
    void setDefaultStyle();

    void createAnimation();

    static inline void startAnimation(QPropertyAnimation *animation);

    static inline void stopAnimation(QPropertyAnimation *animation);

    inline int calculateChangedValue(bool isRise);

  private:
    QFont textFont_;
    QColor textColor_;
    QFont textHoverFont_;
    QColor textHoverColor_;
    QFont textDisableFont_;
    QColor textDisableColor_;

    // 滑动条 三态 背景颜色
    QColor sliderBgColor_;
    QColor sliderBgHoverColor_;
    QColor sliderBgDisableColor_;

    // 滑动条 滑轨 正常背景颜色、 高度、圆角
    QList<QColor> sliderGrooveBgColorList_;
    int sliderGrooveHeight_;
    int sliderGrooveRadius_;

    // 滑动条 滑轨 高亮背景颜色、 高度、圆角
    QList<QColor> sliderGrooveHoverBgColorList_;
    int sliderGrooveHoverHeight_;
    int sliderGrooveHoverRadius_;

    // 滑动条 滑轨 禁用背景颜色、 高度、圆角
    QList<QColor> sliderGrooveDisableBgColorList_;
    int sliderGrooveDisableHeight_;
    int sliderGrooveDisableRadius_;

    QList<QColor> sliderZeroScaleColorList_;

    // 滑动条 三态 背景颜色
    QList<QColor> sliderSubPageBgColorList_;
    QList<QColor> sliderSubPageHoverBgColorList_;
    QList<QColor> sliderSubPageDisableBgColorList_;

    QColor sliderHandleBgColor_;
    int sliderHandleWidth_;
    int sliderHandleHeight_;
    int sliderHandleRadius_;

    QColor sliderHandleHoverBgColor_;
    int sliderHandleHoverWidth_;
    int sliderHandleHoverHeight_;
    int sliderHandleHoverRadius_;

    QColor sliderHandleDisableBgColor_;
    int sliderHandleDisableWidth_;
    int sliderHandleDisableHeight_;
    int sliderHandleDisableRadius_;

    QColor sliderHandleBorderColor_;
    int sliderHandleBorderWidth_;

    QColor sliderHandleHoverBorderColor_;
    int sliderHandleHoverBorderWidth_;

    QColor sliderHandleDisableBorderColor_;
    int sliderHandleDisableBorderWidth_;

    int maxValue_{100};
    int minValue_{0};
    int curValue_{0};
    int lastValue_{0};
    int defaultValue_{0};
    int textAlignmentFlag_{0};
    int singleStep_{1};
    int borderMaxWidth_{0};
    double sliderIncrement{0.0};
    double curHandleBorderWidth_{2.0};
    std::atomic<bool> isDragable{false};
    std::atomic<bool> isHovered{false};
    std::atomic<bool> handleAnimationEnable_{false};
    std::atomic<bool> eventEnable_{true};
    bool mouseFirstPressedOnHandle_{false};
    QString sliderTextContent_;
    QRectF sliderBgRect;
    QRectF sliderGrooveRect;
    QRectF sliderHandleRect;
    QRectF sliderMouseRect;

    QPropertyAnimation *zoomInAnimation_{};
    QPropertyAnimation *zoomOutAnimation_{};
    std::vector<std::tuple<int, int, int, int>> sliderStepRulesTuple_;
    std::vector<std::tuple<int, int, double, double, double>> sliderMappingTuple_;
};

#endif // MLADDERSTEPSLIDER_H
